package com.zkh.myutils.proxy;

import java.util.List;
import java.util.Map;

import com.zkh.myutils.io.log.Logger;
import com.zkh.myutils.proxy.util.TypeBean;
import com.zkh.myutils.proxy.util.TypeHandler;
import com.zkh.myutils.utils.Assert;
import com.zkh.myutils.utils.AuthTree;
import com.zkh.myutils.utils.StringUtils;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassVisitor;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
import jdk.internal.org.objectweb.asm.Type;

/**
 * 打印<b>代理类</b>类，ClassVisitor子类，用于生成新类
 * @author zkh
 */
public class ProxyClassPrinter extends ClassVisitor {
	//代理异常名称
	private static String proxyExceptionName = "com/zkh/myutils/proxy/util/ProxyException";
	//方法代理处理器名称
	private static String methodHandlerName = "com/zkh/myutils/proxy/MethodHandler";
	//方法代理处理器描述
	private static String methodHandlerDesc = "L" + methodHandlerName + ";";
	//代理方法名称
	private static String proxyMethodName = "com/zkh/myutils/proxy/ProxyMethod";
	//代理方法描述
	private static String proxyMethodDesc = "L" + proxyMethodName + ";";
	//代理类名称
	private String proxyClassName;
	//代理类描述符
	private String proxyClassDesc;
	//原类名
	private String originClassName;
	//代理方法正则，对满足正则的方法代理
	private String proxyMethodNameRegexp;
	//接口
	private boolean isInterface;
	//被代理类类型描述
	private String typeDesc;
	//参数映射
	private Map<String, List<String>> paramMap;
	
	/**
	 * 构造方法，默认ASM4
	 * @param cv ClassVisitor对象，此处应为ClassWriter对象
	 * @param proxyClassName 代理类名称
	 * @param proxyMethodNameRegexp 代理方法名称正则
	 * @param type 被代理类的类型，通过枚举类ClassType传入
	 */
	public ProxyClassPrinter(ClassVisitor cv, String proxyClassName, String proxyMethodNameRegexp, ClassType type, Map<String, List<String>> paramMap) {
		super(Opcodes.ASM4, cv);
		//代理类名称
		this.proxyClassName = proxyClassName.replace('.', '/');
		//代理类描述符
		this.proxyClassDesc = "L" + this.proxyClassName + ";";
		this.proxyMethodNameRegexp = proxyMethodNameRegexp;
		//接口标识
		isInterface = type.index==0;
		//被代理类类型描述
		typeDesc = StringUtils.decode(String.valueOf(type.index), "0", "接口", "1", "抽象类", "普通类");
		//参数映射
		this.paramMap = paramMap;
	}

	/**
	 * 读取类整体
	 * @param version 版本
	 * @param access 修饰符
	 * @param name 全类名描述符
	 * @param signature 泛型
	 * @param superName 父类（单个）
	 * @param interfaces 实现接口（可多个）
	 */
	public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
		//输出日志
		Logger.debug("被代理类" + name + "为" + typeDesc + "，生成的代理类" + (isInterface?"实现于被代理接口":"继承自被代理类") + "。");
		//接口
		if(isInterface) {
			//实现接口
			cv.visit(version, Opcodes.ACC_PUBLIC, proxyClassName, signature, superName, new String[] {name});
		}else {
			//继承类
			cv.visit(version, Opcodes.ACC_PUBLIC, proxyClassName, signature, name, interfaces);
		}
		//保存原类名
		originClassName = name;
		//预处理字段和方法
		preDeal();
	}
	
	/**
	 * 预处理字段和方法
	 */
	private void preDeal() {
		//创建字段，存放代理处理器。参数依次为：access, name, desc, signature, value
		cv.visitField(Opcodes.ACC_PRIVATE, "_proxyHandler", methodHandlerDesc, null, null);
		//创建字段，存放方法反射对象
		//cv.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "_proxyMethodMap", "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;"+proxyMethodDesc+">;", null);
		cv.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "_proxyMethodMap", "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;Ljava/lang/reflect/Method;>;", null);
		//创建字段，存放方法和参数名映射
		cv.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "argNamesMap", "Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;Ljava/util/List<Ljava/lang/String;>;>;", null);
		//创建字段，存放类名
		cv.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "className", "Ljava/lang/String;", null, null);
		//创建字段，存放父类名
		cv.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, "superClassName", "Ljava/lang/String;", null, null);
		//创建自定义构造方法。参数依次为：int access, String name, String desc, String signature, String[] exceptions
		MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(" + methodHandlerDesc + ")V", null, null);
		/** 含代理处理器的构造器 **/
		{
			//开始写代码
			mv.visitCode();
			//标记
			Label l0 = new Label();
			mv.visitLabel(l0);
			//加载this
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			//调用super()
			mv.visitMethodInsn(Opcodes.INVOKESPECIAL, isInterface ? "java/lang/Object" : originClassName, "<init>", "()V", false);
			//标记
			Label l1 = new Label();
			mv.visitLabel(l1);
			//加载this
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			//加载第一个参数
			mv.visitVarInsn(Opcodes.ALOAD, 1);
			//参数依次为：int opc, String owner, String name, String desc
			mv.visitFieldInsn(Opcodes.PUTFIELD, proxyClassName, "_proxyHandler", methodHandlerDesc);	//将参数写入字段
			//标记
			Label l2 = new Label();
			mv.visitLabel(l2);
			//返回空
			mv.visitInsn(Opcodes.RETURN);
			//标记
			Label l3 = new Label();
			mv.visitLabel(l3);
			//变量命名
	        mv.visitLocalVariable("handler", methodHandlerDesc, null, l0, l3, 1);
	        //栈和帧大小
			mv.visitMaxs(2, 2);
			//结束写代码
			mv.visitEnd();
		}

		/** static代码块，用于初始化字段 **/
		{
			//创建static代码块，用于初始化字段
			mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
			//开始写内容
			mv.visitCode();
			//实例化HashMap
			mv.visitTypeInsn(Opcodes.NEW, "java/util/HashMap");
	        mv.visitInsn(Opcodes.DUP);
	        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/HashMap", "<init>", "()V", false);
	        //保存实例化后的对象
	        mv.visitFieldInsn(Opcodes.PUTSTATIC, proxyClassName, "_proxyMethodMap", "Ljava/util/Map;");
	        //类名和父类名
	        mv.visitLdcInsn(proxyClassName.replace('/', '.'));
	        mv.visitFieldInsn(Opcodes.PUTSTATIC, proxyClassName, "className", "Ljava/lang/String;");
	        mv.visitLdcInsn(originClassName.replace('/', '.'));
	        mv.visitFieldInsn(Opcodes.PUTSTATIC, proxyClassName, "superClassName", "Ljava/lang/String;");
	        //返回
	        mv.visitInsn(Opcodes.RETURN);
	        mv.visitMaxs(2, 0);
			//结束写代码
			mv.visitEnd();
		}
		/** 处理方法容器的公共方法 **/
        mv = cv.visitMethod(Opcodes.ACC_PRIVATE, "getMethodCache", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", "(Ljava/lang/String;[Ljava/lang/Class<*>;)Ljava/lang/reflect/Method;", null);
        mv.visitCode();
        Label l0 = new Label();
        Label l1 = new Label();
        Label l2 = new Label();
        mv.visitTryCatchBlock(l0, l1, l2, "java/lang/NoSuchMethodException");
        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "_proxyMethodMap", "Ljava/util/Map;");
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "containsKey", "(Ljava/lang/Object;)Z", true);
        Label l4 = new Label();
        mv.visitJumpInsn(Opcodes.IFNE, l4);
        mv.visitLabel(l0);
        mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "_proxyMethodMap", "Ljava/util/Map;");
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn(Type.getType(proxyClassDesc));
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitVarInsn(Opcodes.ALOAD, 2);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getMethod", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitInsn(Opcodes.POP);
        mv.visitLabel(l1);
        mv.visitJumpInsn(Opcodes.GOTO, l4);
        mv.visitLabel(l2);
        mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[]{"java/lang/NoSuchMethodException"});
        mv.visitVarInsn(Opcodes.ASTORE, 3);
        Label l5 = new Label();
        mv.visitLabel(l5);
        mv.visitTypeInsn(Opcodes.NEW, proxyExceptionName);
        mv.visitInsn(Opcodes.DUP);
        mv.visitVarInsn(Opcodes.ALOAD, 3);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyExceptionName, "<init>", "(Ljava/lang/Throwable;)V", false);
        mv.visitInsn(Opcodes.ATHROW);
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "_proxyMethodMap", "Ljava/util/Map;");
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
        mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/reflect/Method");
        mv.visitInsn(Opcodes.ARETURN);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitLocalVariable("e", "Ljava/lang/NoSuchMethodException;", null, l5, l4, 3);
        mv.visitLocalVariable("this", proxyClassDesc, null, l3, l6, 0);
        mv.visitLocalVariable("key", "Ljava/lang/String;", null, l3, l6, 1);
        mv.visitLocalVariable("argClasses", "[Ljava/lang/Class;", "[Ljava/lang/Class<*>;", l3, l6, 2);
        mv.visitMaxs(5, 4);
        mv.visitEnd();
	}
	
	/**
	 * 读取source代码
	 * @param source
	 * @param debug
	 */
	public void visitSource(String source, String debug) {
		cv.visitSource(source, debug);
	}

	/**
	 * 读取外部类
	 * @param owner
	 * @param name
	 * @param desc
	 */
	public void visitOuterClass(String owner, String name, String desc) {
		cv.visitOuterClass(owner, name, desc);
	}

	/**
	 * 读取注解
	 * @param desc
	 * @param visible
	 * @return
	 */
	public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
		return cv.visitAnnotation(desc, visible);
	}
	
	/**
	 * 读取属性
	 * @param attr
	 */
	public void visitAttribute(Attribute attr) {
		cv.visitAttribute(attr);
	}
	
	/**
	 * 读取内部类
	 * @param name
	 * @param outerName
	 * @param innerName
	 * @param access
	 */
	public void visitInnerClass(String name, String outerName, String innerName, int access) {
		cv.visitInnerClass(name, outerName, innerName, access);
	}
	
	/**
	 * 读取字段，生成的代理类不要父类字段
	 * @param access 修饰符
	 * @param name 字段名
	 * @param desc 字段类型（描述符）
	 * @param signature 泛型
	 * @param value 常量值（非常量必须给null）
	 * @return
	 */
	public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
		return null;
	}
	
	/**
	 * 读取方法
	 * @param access 修饰符
	 * @param name 方法名
	 * @param desc 参数及返回值
	 * @param signature 泛型
	 * @param exceptions 可抛出的异常（数组）
	 * @return
	 */
	public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
		//将access转换为权限树
		AuthTree authTree = new AuthTree(access);
		//私有方法，受保护方法、静态方法和final方法，直接跳过
		if(authTree.existAuth(Opcodes.ACC_PRIVATE, Opcodes.ACC_PROTECTED, Opcodes.ACC_STATIC, Opcodes.ACC_FINAL)) {
			return null;
		}
		//构造方法，直接跳过
		else if("<init>".equals(name)) {
			return null;
		}
		//可以生成代理
		else {
			//抽象方法标识
			boolean isAbstract = authTree.hasAuth(Opcodes.ACC_ABSTRACT);
			//如果是抽象方法，去除抽象修饰符
			if(isAbstract) {
				authTree.removeAuth(Opcodes.ACC_ABSTRACT);
			}
			//处理返回值
			Type rtnType = Type.getReturnType(desc);
			//返回值转换
			TypeBean rtnTypeBean = new TypeBean(rtnType, rtnType.getSize(), rtnType.getDescriptor(), rtnType.getClassName());
			/** 生成代理方法 **/
			//获取并处理参数
			TypeHandler handler = TypeHandler.getTypeList(Type.getArgumentTypes(desc));
			//不代理条件
			if(!isAbstract && !name.matches(proxyMethodNameRegexp)) {
				//创建一个代理方法
				MethodVisitor proxymv = cv.visitMethod(Opcodes.ACC_PUBLIC, name, desc, signature, exceptions);
				//填充代理方法内容
				renderProxyMethod(proxymv, handler, rtnTypeBean, name, desc);
				return null;
			}else {
				//读取原方法
				MethodVisitor mv = cv.visitMethod(authTree.getIntAuth(), name, desc, signature, exceptions);
				//日志
				Logger.debug("为"+Assert.getIfElse(isAbstract,"抽象","普通")+"方法" + originClassName + "::" + name + "->" + desc + " 创建代理");
				//创建一个代理方法
				MethodVisitor proxymv = cv.visitMethod(Opcodes.ACC_PUBLIC, name + "$$" + handler.getAutograph(), desc, signature, exceptions);
				//填充代理方法内容
				renderProxyMethod(proxymv, handler, rtnTypeBean, name, Assert.getIfElse(isAbstract, null, desc));
				//写入当前方法内容
				writeMethodBody(mv, name, handler, rtnTypeBean, isAbstract);
				//返回方法
				return Assert.getIfElse(isAbstract, mv, null);
			}
		}
	}
	
	/**
	 * 写入当前方法内容
	 * @param mv MethodVisitor
	 * @param name 方法名称
	 * @param handler 参数类型处理器
	 * @param rtnTypeBean 返回值
	 */
	private void writeMethodBody(MethodVisitor mv, String name, TypeHandler handler, TypeBean rtnTypeBean, boolean isAbstract) {
		mv.visitCode();
		Label l0 = new Label();
		Label l1 = new Label();
		Label l2 = new Label();
		mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
		Label l3 = new Label();
		mv.visitLabel(l3);
		//Utils.ifElse(handler.getNumber()>5, ()->mv.visitIntInsn(Opcodes.BIPUSH, handler.getNumber()), ()->mv.visitInsn(3 + handler.getNumber()));
		mv.visitIntInsn(Opcodes.BIPUSH, handler.getNumber());
		mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
		//遍历参数
		handler.beanForeach(iter->{
			//当前类型
			TypeBean bean = iter.getBean();
			//执行指令
			mv.visitInsn(Opcodes.DUP);
			mv.visitIntInsn(Opcodes.BIPUSH, iter.getIndex());
			//原始类型通过静态方法获取Class
			if(bean.isOriginType()) {
				//方法描述
				String[] mds = bean.getMethodDesc();
				//类型和帧位置
			    mv.visitVarInsn(bean.getLoadType(), Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
			    //类型转换
			    mv.visitMethodInsn(Opcodes.INVOKESTATIC, mds[0], "valueOf", mds[1], false);
			}else {
			    mv.visitVarInsn(Opcodes.ALOAD, Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
			}
			//储存
			mv.visitInsn(Opcodes.AASTORE);
		});
        //存储数组地址
		mv.visitVarInsn(Opcodes.ASTORE, 1 + handler.getTotal());
		mv.visitLabel(l0);
		mv.visitLdcInsn(name);
		mv.visitVarInsn(Opcodes.ASTORE, 2 + handler.getTotal());
		Label l4 = new Label();
		mv.visitLabel(l4);
		mv.visitLdcInsn(handler.getAutograph());
		mv.visitVarInsn(Opcodes.ASTORE, 3 + handler.getTotal());
		Label l5 = new Label();
		mv.visitLabel(l5);
		mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
		mv.visitInsn(Opcodes.DUP);
		mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false);
		mv.visitVarInsn(Opcodes.ALOAD, 2 + handler.getTotal());
		mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
		mv.visitLdcInsn("$$");
		mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
		mv.visitVarInsn(Opcodes.ALOAD, 3 + handler.getTotal());
		mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
		mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
		mv.visitVarInsn(Opcodes.ASTORE, 4 + handler.getTotal());
		Label l6 = new Label();
		mv.visitLabel(l6);
		mv.visitVarInsn(Opcodes.ALOAD, 0);
		mv.visitVarInsn(Opcodes.ALOAD, 4 + handler.getTotal());
		//定义参数类型数组
		mv.visitIntInsn(Opcodes.BIPUSH, handler.getNumber());
		mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Class");
		//遍历参数
		handler.beanForeach(iter->{
			//当前类型
			TypeBean bean = iter.getBean();
			//执行指令
			mv.visitInsn(Opcodes.DUP);
			mv.visitIntInsn(Opcodes.BIPUSH, iter.getIndex());
			//原始类型通过静态方法获取Class
		    if(bean.isOriginType()) {
		    	mv.visitFieldInsn(Opcodes.GETSTATIC, bean.getWrapType(), "TYPE", "Ljava/lang/Class;");
		    }else {
		    	mv.visitLdcInsn(iter.getBean().getType());
		    }
		    mv.visitInsn(Opcodes.AASTORE);
		});
        //调用getMethodCache方法
		mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyClassName, "getMethodCache", "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;", false);
		mv.visitVarInsn(Opcodes.ASTORE, 5 + handler.getTotal());
		Label l7 = new Label();
		mv.visitLabel(l7);
		mv.visitVarInsn(Opcodes.ALOAD, 0);
		mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassName, "_proxyHandler", methodHandlerDesc);
		mv.visitVarInsn(Opcodes.ALOAD, 0);
		mv.visitTypeInsn(Opcodes.NEW, proxyMethodName);
		mv.visitInsn(Opcodes.DUP);
		mv.visitVarInsn(Opcodes.ALOAD, 5 + handler.getTotal());
		mv.visitVarInsn(Opcodes.ALOAD, 4 + handler.getTotal());
		mv.visitVarInsn(Opcodes.ALOAD, 2 + handler.getTotal());
		mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "className", "Ljava/lang/String;");
		mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "superClassName", "Ljava/lang/String;");
		mv.visitVarInsn(Opcodes.ALOAD, 1 + handler.getTotal());
		mv.visitFieldInsn(Opcodes.GETSTATIC, proxyClassName, "argNamesMap", "Ljava/util/Map;");
		mv.visitVarInsn(Opcodes.ALOAD, 4 + handler.getTotal());
		mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
		mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/List");
		mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyMethodName, "<init>", "(Ljava/lang/reflect/Method;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;Ljava/util/List;)V", false);
		mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, methodHandlerName, "invoke", "(Ljava/lang/Object;"+proxyMethodDesc+")Ljava/lang/Object;", true);
		mv.visitVarInsn(Opcodes.ASTORE, 6 + handler.getTotal());
		Label l8 = new Label();
		mv.visitLabel(l8);
		//处理返回值
		mv.visitVarInsn(Opcodes.ALOAD, 6 + handler.getTotal());
		//转换类型，并返回类型标识
        int rtnFlag = rtnTypeBean.getReturnTypeCast(mv);
		mv.visitLabel(l1);
		//设置返回类型标识
		mv.visitInsn(rtnFlag);
		mv.visitLabel(l2);
		mv.visitFrame(Opcodes.F_FULL, 2 + handler.getNumber(), handler.getFrameView(proxyClassName), 1, new Object[]{"java/lang/Throwable"});            
		mv.visitVarInsn(Opcodes.ASTORE, 2 + handler.getTotal());
		Label l9 = new Label();
		mv.visitLabel(l9);
		mv.visitTypeInsn(Opcodes.NEW, proxyExceptionName);
		mv.visitInsn(Opcodes.DUP);
		mv.visitVarInsn(Opcodes.ALOAD, 2 + handler.getTotal());
		mv.visitMethodInsn(Opcodes.INVOKESPECIAL, proxyExceptionName, "<init>", "(Ljava/lang/Throwable;)V", false);
		mv.visitInsn(Opcodes.ATHROW);
		//设置变量名
		Label l10 = new Label();
		mv.visitLabel(l10);
		mv.visitLocalVariable("name", "Ljava/lang/String;", null, l4, l2, 2 + handler.getTotal());
		mv.visitLocalVariable("autograph", "Ljava/lang/String;", null, l5, l2, 3 + handler.getTotal());
		mv.visitLocalVariable("key", "Ljava/lang/String;", null, l6, l2, 4 + handler.getTotal());
		mv.visitLocalVariable("method", "Ljava/lang/reflect/Method;", null, l7, l2, 5 + handler.getTotal());
		mv.visitLocalVariable("rtn", "Ljava/lang/Object;", null, l8, l2, 6 + handler.getTotal());
		mv.visitLocalVariable("e", "Ljava/lang/Throwable;", null, l9, l10, 2 + handler.getTotal());
		mv.visitLocalVariable("this", proxyClassDesc, null, l3, l10, 0);
		//获取变量名称
		List<String> paramNames = paramMap.get(name + "$$" + handler.getAutograph());
		//依次设置变量名
		handler.beanForeach(iter->{
			//变量名
			String varname = paramNames==null ? ("var" + iter.getIndex()) : paramNames.get(iter.getIndex());
			//设置变量名
			mv.visitLocalVariable(varname, iter.getBean().getDescriptor(), null, l3, l6, Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
		});
		
		mv.visitLocalVariable("args", "[Ljava/lang/Object;", null, l0, l10, 1 + handler.getTotal());
		mv.visitMaxs(12, 7 + handler.getTotal());
		mv.visitEnd();
	}
	
	/**
	 * 填充代理方法
	 * @param proxymv 代理方法的MethodVisitor对象
	 * @param handler 参数处理器
	 * @param rtnTypeBean 返回类型对象
	 * @param name 方法名
	 * @param desc 方法描述
	 */
	private void renderProxyMethod(MethodVisitor mv, TypeHandler handler, TypeBean rtnTypeBean,String name, String desc) {
		//获取变量名称
		List<String> paramNames = paramMap.get(name + "$$" + handler.getAutograph());
		//抽象方法
		if(desc==null) {
			//开始访问
			mv.visitCode();
			//设置标记0
	        Label l0 = new Label();
	        mv.visitLabel(l0);
	        //返回
	        mv.visitInsn(rtnTypeBean.getReturnType(mv));
			//设置标记1
	        Label l1 = new Label();
	        mv.visitLabel(l1);
	        //依次设置变量名
			handler.beanForeach(iter->{
    			//变量名
    			String varname = paramNames==null ? ("var" + iter.getIndex()) : paramNames.get(iter.getIndex());
    			//设置变量
				mv.visitLocalVariable(varname, iter.getBean().getDescriptor(), null, l0, l1, Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
			});
			//设置栈和帧长度
			mv.visitMaxs(rtnTypeBean.getLength(), 1 + handler.getTotal());
			//结束
			mv.visitEnd();
		}else {
			//开始访问
			mv.visitCode();
			//设置标记0
			Label l0 = new Label();
			mv.visitLabel(l0);
			//依次加载参数
			mv.visitVarInsn(Opcodes.ALOAD, 0);
			handler.beanForeach(iter->{
				//bean
				TypeBean tb = iter.getBean();
				//加载参数指令
				mv.visitVarInsn(Assert.getIfElse(tb.isOriginType(), tb.getLoadType(), Opcodes.ALOAD), Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
			});
			//调用父类方法
			mv.visitMethodInsn(Opcodes.INVOKESPECIAL, originClassName, name, desc, false);
			//返回
			mv.visitInsn(rtnTypeBean.getReturnType(null));
			//设置标记1
            Label l1 = new Label();
            mv.visitLabel(l1);
            //设置参数变量
            mv.visitLocalVariable("this", proxyClassDesc, null, l0, l1, 0);
            handler.beanForeach(iter->{
    			//变量名
    			String varname = paramNames==null ? ("var" + iter.getIndex()) : paramNames.get(iter.getIndex());
    			//设置变量
				mv.visitLocalVariable(varname, iter.getBean().getDescriptor(), null, l0, l1, Assert.getIfElse(iter.getBean().getLength()==2, iter.getFrame()-1, iter.getFrame()));
			});
            
			//设置栈和帧长度
			mv.visitMaxs(1+handler.getTotal(), 1 + handler.getTotal());
			mv.visitEnd();
		}
	}
	
	/**
	 * 读取结束
	 */
	public void visitEnd() {
		cv.visitEnd();
	}
}
